-- Field of Vision and heading


-- Check if a tile (tloc) is visible to a character at (loc) with heading (heading)
function ComputeFOV(loc, heading, tloc, range, alert)

	local isVisible = false

	local xdist = 0
	local ydist = 0

	if (alert == true) then 
		xdist = tloc[1] - loc[1] + 2*heading[1]
		ydist = tloc[2] - loc[2] + 2*heading[2]
		range = range + 1
	else
		xdist = tloc[1] - loc[1] + heading[1]
		ydist = tloc[2] - loc[2] + heading[2]
	end

	if (xdist*xdist + ydist*ydist >= range*range) then return false end

	local norm = math.sqrt(xdist*xdist + ydist*ydist)*math.sqrt(math.pow(heading[1],2) + math.pow(heading[2],2))

	local dotprod = (xdist*heading[1] +ydist*heading[2])/norm

	-- First check angle from heading
	if (math.acos(dotprod) < math.pi/4) then
		isVisible = true
	else
		isVisible = false
	end

	-- now check LOS
	if (isVisible == true) then
		if (lineofsight(loc[1],loc[2],tloc[1],tloc[2], isLOSBlocked) == false ) then
			 isVisible = false
		 end

		 -- check back
		 if (lineofsight(tloc[1],tloc[2],loc[1],loc[2], isLOSBlocked) == false ) then
			 isVisible = false
		 end
	end

	return isVisible
end

function CheckFOV(dead)

	if (dead == nil ) then local dead = false end

--	Check based on rough angle
	for i = 1, worldData.size.x, 1 do
		for j = 1,worldData.size.y,1 do

			-- Player FOV
			if (dead == false) then
				localTerrain[i][j].FOV = ComputeFOV(characterLoc,playerHeading.value, {i,j},10, false)
			else
				localTerrain[i][j].FOV = true
			end

			-- Mob FOV
			localTerrain[i][j].MobFOV = {}

			-- trees not in FOV for mobs
			if (isMoveBlocked(i,j) == false or ( characterLoc[1] == i and characterLoc[2] ==j ) == true ) then

				local index = 1
				local mobList = activeMobs
			    while mobList do
			    	if (mobList.value.alive == true and offPage(mobList.value.x,mobList.value.y) == false) then
				    	if ComputeFOV({mobList.value.x,mobList.value.y},mobList.value.heading.value, {i,j},mobList.value.range, mobList.value.alerted) == true then
				    		localTerrain[i][j].MobFOV[index] = mobList.value
				    		index = index + 1
				    	end
				    end
			    	mobList = mobList.next
			    end
			 end

		end
	end

end

-- Clear FOV tags in each tile for deepcopy
function clearFOV()
	for i = 1, worldData.size.x, 1 do
		for j = 1,worldData.size.y,1 do
			localTerrain[i][j].MobFOV = {}
		end
	end
end


function genHeading()
	-- Heading circular linked list
	heading = circularlist{	
									{0,1, 	quad = love.graphics.newQuad(0*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 1 },
									{1,1, 	quad = love.graphics.newQuad(1*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 2 },
									{1,0, 	quad = love.graphics.newQuad(2*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 3 },
									{1,-1, 	quad = love.graphics.newQuad(3*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 4 },
									{0,-1, 	quad = love.graphics.newQuad(4*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 5 },
									{-1,-1, quad = love.graphics.newQuad(5*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 6 },
									{-1,0, 	quad = love.graphics.newQuad(6*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 7 },
									{-1,1, 	quad = love.graphics.newQuad(7*tileSize,2*tileSize,tileSize,tileSize,320,96), index = 8 }
								}


	for i=0,math.random(9),1 do
		heading = heading.next
	end

	return heading
end

-- get the best heading to get a line on the target
function getBestHeading(cLoc, cHeading, target, range)

-- cant see target, see if you can rotate
	local tHeading = cHeading
	local index = 1

	local visibleHeadings = {}

	for i=1,8,1 do
		if (ComputeFOV(cLoc, tHeading.value, target, range, true) == true) then
			visibleHeadings[index] = tHeading
			index = index+1
		end
		tHeading = tHeading.next
	end 

	-- no possible angle
	if (#visibleHeadings == 0) then return nil end
	if (#visibleHeadings == 1) then return visibleHeadings[1] end

	local diff = { target[1] - cLoc[1], target[2] - cLoc[2]}
	local diffnorm = math.sqrt(diff[1]*diff[1] + diff[2]*diff[2])

	diff[1] = diff[1]/diffnorm
	diff[2] = diff[2]/diffnorm

	local maxDP = -1
	local maxDPindx = 1

	for i=1,#visibleHeadings,1 do
		local norm = math.sqrt(visibleHeadings[i].value[1]*visibleHeadings[i].value[1] + visibleHeadings[i].value[2]*visibleHeadings[i].value[2])
		local dp = (visibleHeadings[i].value[1]*diff[1]+visibleHeadings[i].value[2]*diff[2])/norm

		-- find maximum dot product
		if (dp > maxDP) then 
			maxDP = dp
			maxDPindx = i
		end

	end

	return visibleHeadings[maxDPindx]

end





















